package gui;

import java.awt.EventQueue;

import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableModel;

import java.awt.GridLayout;

import javax.swing.JLabel;
import javax.swing.JTextField;

import java.awt.Color;
import java.awt.Font;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import java.awt.Window;

import javax.swing.JTable;
import javax.swing.JButton;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.SwingConstants;

import constant.Constant;
import business.BusinessImpl;
import dto.DTOClass;
import dto.DTOContact;
import dto.DTORelation;

import javax.swing.JComboBox;

import java.awt.Component;

import javax.swing.Box;
import javax.swing.BoxLayout;

/**
 * @author Jonathan Maret This class is used to manage classes, it create a
 *         windows containing different option to update/create or remove a
 *         class
 * 
 */
public class ClassManaging extends JDialog implements ActionListener {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private JPanel contentPane;
	private JTextField txtName;
	private JTable tblStudent;
	private JTable tblTeacher;
	private BusinessImpl businessImpl = new BusinessImpl();
	private Constant constant = new Constant();

	// the currently selected class
	private DTOClass selectedClass;
	private JPanel pnlCheck;
	private JComboBox<?> cbxHolder;
	private JLabel lblCheck;
	private JLabel lblSuccess;

	public DTOClass getSelectedClass() {
		return selectedClass;
	}

	// this class work a lot with the selectedClass variable, when the class is
	// updated, it launch a refresh
	public void setSelectedClass(DTOClass selectedClass) {
		this.selectedClass = selectedClass;
		refreshClass(selectedClass);

	}

	/**
	 * Launch the application, can be used for debugging without launching the
	 * main application
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					ClassManaging frame = new ClassManaging();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public ClassManaging() {
		this.setModal(true);
		// define the interface, everything is in a gridbaglayout
		this.setTitle("Ajout d'une nouvelle classe ");
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		setBounds(100, 100, 577, 510);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		GridBagLayout gbl_contentPane = new GridBagLayout();
		gbl_contentPane.columnWidths = new int[] { 335, 0, 0 };
		gbl_contentPane.rowHeights = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0 };
		gbl_contentPane.columnWeights = new double[] { 1.0, 1.0,
				Double.MIN_VALUE };
		gbl_contentPane.rowWeights = new double[] { 0.0, 0.0, 0.0, 0.0, 0.0,
				0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, Double.MIN_VALUE };
		contentPane.setLayout(gbl_contentPane);

		JPanel panel = new JPanel();
		GridBagConstraints gbc_panel = new GridBagConstraints();
		gbc_panel.gridwidth = 2;
		gbc_panel.insets = new Insets(0, 0, 5, 0);
		gbc_panel.fill = GridBagConstraints.BOTH;
		gbc_panel.gridx = 0;
		gbc_panel.gridy = 0;
		contentPane.add(panel, gbc_panel);
		panel.setLayout(new GridLayout(1, 0, 0, 0));

		JButton btnSelect = new JButton("Selectionner une classe");
		btnSelect.setName("btnSelect");
		btnSelect.addActionListener(this);
		panel.add(btnSelect);

		JButton btnNewClass = new JButton("Nouvelle classe");
		btnNewClass.setName("btnNewClass");
		btnNewClass.addActionListener(this);
		panel.add(btnNewClass);

		JButton btnDelClass = new JButton("Supprimer une classe");
		btnDelClass.setName("btnDelClass");
		btnDelClass.addActionListener(this);
		panel.add(btnDelClass);

		lblCheck = new JLabel("Veuillez controler la validier de vos donneés");
		lblCheck.setVisible(false);
		GridBagConstraints gbc_lblCheck = new GridBagConstraints();
		gbc_lblCheck.gridwidth = 2;
		gbc_lblCheck.insets = new Insets(0, 0, 5, 0);
		gbc_lblCheck.gridx = 0;
		gbc_lblCheck.gridy = 1;
		contentPane.add(lblCheck, gbc_lblCheck);
		lblCheck.setFont(new Font("Tahoma", Font.BOLD, 11));
		lblCheck.setForeground(Color.RED);

		lblSuccess = new JLabel("Les données ont été enregistrées avec succès");
		lblSuccess.setVisible(false);
		lblSuccess.setFont(new Font("Tahoma", Font.BOLD, 11));
		lblSuccess.setForeground(Color.GREEN);
		GridBagConstraints gbc_lblSuccess = new GridBagConstraints();
		gbc_lblSuccess.gridwidth = 2;
		gbc_lblSuccess.insets = new Insets(0, 0, 5, 5);
		gbc_lblSuccess.gridx = 0;
		gbc_lblSuccess.gridy = 2;
		contentPane.add(lblSuccess, gbc_lblSuccess);

		JLabel lblNom = new JLabel("Nom :");
		GridBagConstraints gbc_lblNom = new GridBagConstraints();
		gbc_lblNom.insets = new Insets(0, 0, 5, 5);
		gbc_lblNom.anchor = GridBagConstraints.EAST;
		gbc_lblNom.gridx = 0;
		gbc_lblNom.gridy = 3;
		contentPane.add(lblNom, gbc_lblNom);

		txtName = new JTextField();
		GridBagConstraints gbc_txtName = new GridBagConstraints();
		gbc_txtName.insets = new Insets(0, 0, 5, 0);
		gbc_txtName.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtName.gridx = 1;
		gbc_txtName.gridy = 3;
		contentPane.add(txtName, gbc_txtName);
		txtName.setColumns(10);

		JLabel lblTitulaire = new JLabel("Titulaire :");
		GridBagConstraints gbc_lblTitulaire = new GridBagConstraints();
		gbc_lblTitulaire.anchor = GridBagConstraints.EAST;
		gbc_lblTitulaire.insets = new Insets(0, 0, 5, 5);
		gbc_lblTitulaire.gridx = 0;
		gbc_lblTitulaire.gridy = 4;
		contentPane.add(lblTitulaire, gbc_lblTitulaire);

		ArrayList<DTOContact> teacher = businessImpl.getAllTeacher();
		Object[] cbxHolderData = new Object[teacher.size()];

		for (int i = 0; i < teacher.size(); i++) {
			cbxHolderData[i] = teacher.get(i);
		}

		cbxHolder = new JComboBox<Object>(cbxHolderData);
		GridBagConstraints gbc_cbxHolder = new GridBagConstraints();
		gbc_cbxHolder.insets = new Insets(0, 0, 5, 0);
		gbc_cbxHolder.fill = GridBagConstraints.HORIZONTAL;
		gbc_cbxHolder.gridx = 1;
		gbc_cbxHolder.gridy = 4;
		contentPane.add(cbxHolder, gbc_cbxHolder);

		JLabel lblListeDesProfesseurs = new JLabel("Liste des Professeurs :");
		lblListeDesProfesseurs.setHorizontalAlignment(SwingConstants.LEFT);
		GridBagConstraints gbc_lblListeDesProfesseurs = new GridBagConstraints();
		gbc_lblListeDesProfesseurs.insets = new Insets(0, 0, 5, 5);
		gbc_lblListeDesProfesseurs.gridx = 0;
		gbc_lblListeDesProfesseurs.gridy = 5;
		contentPane.add(lblListeDesProfesseurs, gbc_lblListeDesProfesseurs);

		tblTeacher = new JTable();
		GridBagConstraints gbc_tblTeacher = new GridBagConstraints();
		gbc_tblTeacher.gridwidth = 2;
		gbc_tblTeacher.insets = new Insets(0, 0, 5, 0);
		gbc_tblTeacher.fill = GridBagConstraints.BOTH;
		gbc_tblTeacher.gridx = 0;
		gbc_tblTeacher.gridy = 6;
		contentPane.add(new JScrollPane(tblTeacher), gbc_tblTeacher);

		JPanel pnlAddDelTeacher = new JPanel();
		GridBagConstraints gbc_pnlAddDelTeacher = new GridBagConstraints();
		gbc_pnlAddDelTeacher.gridwidth = 2;
		gbc_pnlAddDelTeacher.insets = new Insets(0, 0, 5, 0);
		gbc_pnlAddDelTeacher.fill = GridBagConstraints.HORIZONTAL;
		gbc_pnlAddDelTeacher.gridx = 0;
		gbc_pnlAddDelTeacher.gridy = 7;
		contentPane.add(pnlAddDelTeacher, gbc_pnlAddDelTeacher);

		JButton btnAddTeacher = new JButton("Ajouter");
		btnAddTeacher.setName("btnAddTeacher");
		btnAddTeacher.addActionListener(this);
		pnlAddDelTeacher.add(btnAddTeacher);

		JButton btnDelTeacher = new JButton("Supprimer");
		btnDelTeacher.setName("btnDelTeacher");
		btnDelTeacher.addActionListener(this);
		pnlAddDelTeacher.add(btnDelTeacher);

		JLabel lblListeDesElves = new JLabel("Liste des Elèves :");
		lblListeDesElves.setHorizontalAlignment(SwingConstants.LEFT);
		GridBagConstraints gbc_lblListeDesElves = new GridBagConstraints();
		gbc_lblListeDesElves.insets = new Insets(0, 0, 5, 5);
		gbc_lblListeDesElves.gridx = 0;
		gbc_lblListeDesElves.gridy = 8;
		contentPane.add(lblListeDesElves, gbc_lblListeDesElves);

		tblStudent = new JTable();
		GridBagConstraints gbc_tblStudent = new GridBagConstraints();
		gbc_tblStudent.insets = new Insets(0, 0, 5, 0);
		gbc_tblStudent.gridwidth = 2;
		gbc_tblStudent.fill = GridBagConstraints.BOTH;
		gbc_tblStudent.gridx = 0;
		gbc_tblStudent.gridy = 9;
		contentPane.add(new JScrollPane(tblStudent), gbc_tblStudent);

		JPanel pnlAddDelStudent = new JPanel();
		GridBagConstraints gbc_pnlAddDelStudent = new GridBagConstraints();
		gbc_pnlAddDelStudent.insets = new Insets(0, 0, 5, 0);
		gbc_pnlAddDelStudent.gridwidth = 2;
		gbc_pnlAddDelStudent.fill = GridBagConstraints.HORIZONTAL;
		gbc_pnlAddDelStudent.gridx = 0;
		gbc_pnlAddDelStudent.gridy = 10;
		contentPane.add(pnlAddDelStudent, gbc_pnlAddDelStudent);

		JButton btnAddStudent = new JButton("Ajouter");
		btnAddStudent.setName("btnAddStudent");
		btnAddStudent.addActionListener(this);
		pnlAddDelStudent.add(btnAddStudent);

		JButton btnDelStudent = new JButton("Supprimer");
		btnDelStudent.setName("btnDelStudent");
		btnDelStudent.addActionListener(this);
		pnlAddDelStudent.add(btnDelStudent);

		pnlCheck = new JPanel();
		GridBagConstraints gbc_pnlCheck = new GridBagConstraints();
		gbc_pnlCheck.gridwidth = 2;
		gbc_pnlCheck.fill = GridBagConstraints.BOTH;
		gbc_pnlCheck.gridx = 0;
		gbc_pnlCheck.gridy = 11;
		contentPane.add(pnlCheck, gbc_pnlCheck);
		pnlCheck.setLayout(new GridLayout(1, 0, 0, 0));

		JButton btnValidate = new JButton("Valider");
		btnValidate.setName("btnValidate");
		btnValidate.addActionListener(this);
		pnlCheck.add(btnValidate);

		JButton btnCancel = new JButton("Annuler");
		btnCancel.setName("btnCancel");
		btnCancel.addActionListener(this);
		pnlCheck.add(btnCancel);

		JButton btnFinish = new JButton("Terminer");
		btnFinish.setName("btnFinish");
		btnFinish.addActionListener(this);
		pnlCheck.add(btnFinish);
	}

	/**
	 * When a class is selected, refresh everything in the board
	 * 
	 * @param clasS
	 */
	public void refreshClass(DTOClass clasS) {
		if (clasS != null) {
			// load the data into each field
			this.setTitle("Modification de : " + clasS);
			txtName.setText(clasS.toString());
			DTOContact contact;
			ArrayList<DTORelation> relation = businessImpl
					.getAllRelationByClass(clasS);

			ArrayList<ArrayList<Object>> dataTeacher = new ArrayList<ArrayList<Object>>();
			ArrayList<ArrayList<Object>> dataStudent = new ArrayList<ArrayList<Object>>();

			cbxHolder.setSelectedItem(businessImpl.getContactById(clasS
					.getHolder_id()));
			// load relation for the two table, containing the contact
			for (DTORelation dtoRelation : relation) {
				contact = businessImpl.getContactById(dtoRelation
						.getContact_id());
				if (contact != null) {
					ArrayList<Object> temp = new ArrayList<Object>();
					if (contact.getTypeOfContact() == constant
							.typeofcontact("TEACHER")) {
						temp.add(contact);
						temp.add(contact.getLastname());
						temp.add(contact.getFirstname());
						temp.add(contact.getVisa());
						dataTeacher.add(temp);
					}

					else if (contact.getTypeOfContact() == constant
							.typeofcontact("STUDENT")) {
						temp.add(contact);
						temp.add(contact.getLastname());
						temp.add(contact.getFirstname());
						temp.add(contact.getVisa());
						dataStudent.add(temp);
					}

				}
			}

			Object[][] teacher = new Object[dataTeacher.size()][dataTeacher
					.get(0).size()];

			for (int i = 0; i < dataTeacher.size(); i++) {
				for (int j = 0; j < dataTeacher.get(i).size(); j++) {
					teacher[i][j] = dataTeacher.get(i).get(j);
				}
			}

			Object[][] student = new Object[dataStudent.size()][dataStudent
					.get(0).size()];

			for (int i = 0; i < dataStudent.size(); i++) {
				for (int j = 0; j < dataStudent.get(i).size(); j++) {
					student[i][j] = dataStudent.get(i).get(j);
				}
			}

			tblTeacher.setModel(createModelTable(teacher,
					Constant.CONTACT_COLUMNNAMES));
			tblStudent.setModel(createModelTable(student,
					Constant.CONTACT_COLUMNNAMES));

			tblTeacher.removeColumn(tblTeacher.getColumnModel().getColumn(0));
			tblStudent.removeColumn(tblStudent.getColumnModel().getColumn(0));

		} else {
			// is there isn't any class selected, each field blank to enter a
			// new class
			this.setTitle("Ajout d'une nouvelle classe ");
			cbxHolder.setSelectedIndex(0);
			txtName.setText("");
			tblTeacher.setModel(createModelTable());
			tblStudent.setModel(createModelTable());

		}

		this.repaint();
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		// event used for a click on each button, use the source name to execute
		// to right action
		if (e.getSource() instanceof JButton) {
			JButton source = (JButton) e.getSource();

			if (source.getName() == "btnSelect") {
				// in case of a selection click, open a Joptionpane to chose the
				// class to select
				JFrame selectClass = new JFrame();
				Object[] object;

				ArrayList<DTOClass> possibilities = businessImpl.getAllClass();
				possibilities = businessImpl.sortClass(possibilities);
				object = new Object[possibilities.size()];

				for (int i = 0; i < possibilities.size(); i++) {
					object[i] = possibilities.get(i);

				}

				DTOClass clasS = (DTOClass) JOptionPane.showInputDialog(
						selectClass, "Selectionner", "Selection",
						JOptionPane.OK_CANCEL_OPTION, null, object, 0);
				// if the user has chose something, refresh the frame
				setSelectedClass(clasS);

			}
			if (source.getName() == "btnNewClass") {
				// in case of a new class, set the selectedClass to null
				setSelectedClass(null);
			}
			if (source.getName() == "btnDelClass") {
				// open a JOptionPane to remove a class, then ask for a
				// confirmation
				JFrame selectClass = new JFrame();
				Object[] object;

				ArrayList<DTOClass> possibilities = businessImpl.getAllClass();
				object = new Object[possibilities.size()];
				possibilities = businessImpl.sortClass(possibilities);
				for (int i = 0; i < possibilities.size(); i++) {
					object[i] = possibilities.get(i);

				}

				DTOClass clasS = (DTOClass) JOptionPane.showInputDialog(
						selectClass, "Selectionner", "Selection",
						JOptionPane.OK_CANCEL_OPTION, null, object, 0);

				if (clasS != null
						&& JOptionPane
								.showConfirmDialog(
										null,
										"Cette opération est irréversible, voulez-vous continuez ?",
										"Confirmer", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {

					// the user chose and confirm, remove the chosen class
					businessImpl.removeClass(clasS);

				}
			}

			if (source.getName() == "btnAddStudent") {
				// open a JOptionpane to add a student to the student table
				JFrame selectStudent = new JFrame();
				Object[] object;

				ArrayList<DTOContact> possibilities = businessImpl
						.getAllStudentAvailable(selectedClass);
				possibilities = businessImpl.sortContact(possibilities);

				for (int i = 0; i < tblStudent.getModel().getRowCount(); i++) {
					for (int j = possibilities.size() - 1; j >= 0; j--) {
						DTOContact dtoContact = possibilities.get(j);
						if (tblStudent.getModel().getValueAt(i, 0)
								.equals(dtoContact))
							possibilities.remove(j);
					}
				}

				object = new Object[possibilities.size()];

				for (int i = 0; i < possibilities.size(); i++) {
					object[i] = possibilities.get(i);

				}

				DTOContact contact = (DTOContact) JOptionPane.showInputDialog(
						selectStudent, "Selectionner", "Selection",
						JOptionPane.OK_CANCEL_OPTION, null, object, 0);
				if (contact != null)
					addContactToTable(tblStudent, contact);
			}
			if (source.getName() == "btnAddTeacher") {
				// Open a JOptionPane to add a teacher to the teacher table
				JFrame selectTeacher = new JFrame();
				Object[] object;

				ArrayList<DTOContact> possibilities = businessImpl
						.getAllTeacherAvailable(selectedClass);
				possibilities = businessImpl.sortContact(possibilities);

				for (int i = 0; i < tblTeacher.getModel().getRowCount(); i++) {
					for (int j = possibilities.size() - 1; j >= 0; j--) {
						DTOContact dtoContact = possibilities.get(j);
						if (tblTeacher.getModel().getValueAt(i, 0)
								.equals(dtoContact))
							possibilities.remove(j);
					}
				}

				object = new Object[possibilities.size()];

				for (int i = 0; i < possibilities.size(); i++) {
					object[i] = possibilities.get(i);

				}

				DTOContact contact = (DTOContact) JOptionPane.showInputDialog(
						selectTeacher, "Selectionner", "Selection",
						JOptionPane.OK_CANCEL_OPTION, null, object, 0);
				if (contact != null)
					addContactToTable(tblTeacher, contact);
			}
			if (source.getName() == "btnDelTeacher") {
				// remove a teacher from the tblTeacher
				if (tblTeacher.getSelectedRow() > -1) {
					if (tblTeacher.getModel().getValueAt(
							tblTeacher.getSelectedRow(), 0) instanceof DTOContact) {
						removeTableSelectedRow(tblTeacher);
					}

				}
			}
			if (source.getName() == "btnDelStudent") {
				// remove a student from the tblStudent
				if (tblStudent.getSelectedRow() > -1) {
					if (tblStudent.getModel().getValueAt(
							tblStudent.getSelectedRow(), 0) instanceof DTOContact) {
						removeTableSelectedRow(tblStudent);
					}

				}
			}
			if (source.getName() == "btnValidate"
					|| source.getName() == "btnFinish") {
				// if the user press validate or finish button, try to update
				// the database, in case of error will cancel the update
				if (checkDataValidity()) {

					DTOContact holder = (DTOContact) cbxHolder
							.getSelectedItem();
					ArrayList<DTOContact> teacher = getArrayListDTOContact(tblTeacher);
					ArrayList<DTOContact> student = getArrayListDTOContact(tblStudent);

					if (selectedClass != null) {
						selectedClass.setName(txtName.getText());
					} else {

						selectedClass = new DTOClass(0, txtName.getText(),
								holder.getId());
					}

					businessImpl.updateClass(selectedClass, holder, teacher,
							student);
					lblCheck.setVisible(false);
					lblSuccess.setVisible(true);
				} else {
					lblCheck.setVisible(true);
					lblSuccess.setVisible(false);
				}
			}
			if (source.getName() == "btnCancel") {
				// if the user cancel
				this.dispose();
			}
			if (source.getName() == "btnFinish") {
				// if the user finish and the data are valid, dispose the frame
				if (checkDataValidity()) {
					this.dispose();
				}
			}
		}
	}

	private boolean checkDataValidity() {
		// check the validity of the data in the frame
		if (txtName.getText().equals("")) {
			return false;
		} else if (getArrayListDTOContact(tblStudent).size() == 0) {
			return false;
		} else if (getArrayListDTOContact(tblTeacher).size() == 0) {
			return false;
		} else
			return true;

	}

	private void addContactToTable(JTable table, DTOContact contact) {
		// Method to add a contact into a table, used if the user chose to add
		// a student or a teacher
		DefaultTableModel dtm = (DefaultTableModel) table.getModel();
		int nRow = dtm.getRowCount();
		Object[][] tableData = new Object[nRow + 1][4];
		for (int i = 0; i < nRow; i++)
			for (int j = 0; j < 4; j++)
				tableData[i][j] = dtm.getValueAt(i, j);

		tableData[nRow][0] = contact;
		tableData[nRow][1] = contact.getLastname();
		tableData[nRow][2] = contact.getFirstname();
		tableData[nRow][3] = contact.getVisa();

		table.setModel(createModelTable(tableData, Constant.CONTACT_COLUMNNAMES));
		table.removeColumn(table.getColumnModel().getColumn(0));
		table.repaint();
	}

	private void removeTableSelectedRow(JTable table) {
		// when the user chose to remove a contact from a table
		DefaultTableModel dtm = (DefaultTableModel) table.getModel();
		dtm.removeRow(table.getSelectedRow());
		table.setModel(dtm);
	}

	private ArrayList<DTOContact> getArrayListDTOContact(JTable table) {
		// get the all contact into the table as an arrayList
		DefaultTableModel dtm = (DefaultTableModel) table.getModel();
		ArrayList<DTOContact> ret = new ArrayList<DTOContact>();
		int nRow = dtm.getRowCount();

		for (int i = 0; i < nRow; i++)
			ret.add((DTOContact) dtm.getValueAt(i, 0));

		return ret;
	}

	private DefaultTableModel createModelTable(Object[][] tableData,
			Object[] columnNames) {
		// create a tableModel with data if there is at least one contact into
		// the table
		DefaultTableModel dtm = new DefaultTableModel(tableData, columnNames) {

			/**
			 * 
			 */
			private static final long serialVersionUID = 1L;

			@Override
			public boolean isCellEditable(int row, int column) {
				// all cells false
				return false;
			}

		};

		return dtm;
	}

	private DefaultTableModel createModelTable() {
		// create a tableModel if the table is empty
		DefaultTableModel dtm = new DefaultTableModel();
		return dtm;

	}
}
